#pragma once
#include "database_list.h"
#include "widget.h"

#define DB_ID(theKey) #theKey

namespace krryn{
namespace gui{
	class widget_factory{
	public:
		widget* create_widget(const std::string &a_ClassName, const properties &a_Props, widget* a_Parent) const;
	};

	class invalid_widget_node : public krryn::parsers::parse_error{
	public:
		invalid_widget_node(const std::string &a_Element) : parse_error(a_Element) {}
	};

	class database_widgets : public krryn::parsers::database_list{
	public:
		database_widgets(widget_factory &a_Factory);

		widget* get_widget(const std::string &a_Path);
		virtual void load_reserved();
		virtual void build(krryn::parsers::parser_list_node &a_Entry);
	private:
		void build_ui(krryn::parsers::parser_list_node &a_Node, widget* a_Parent);
		void reserve(const std::string &a_Name);
		void add_tree_to_database(krryn::parsers::parser_list_node &a_Node);
		void add_node_to_database(krryn::parsers::parser_list_node &a_Node, const std::string &a_ClassName);
		void add_properties_to_database(krryn::parsers::parser_list_node &a_Node, const std::string &a_Path);
		std::string node_to_path(krryn::parsers::parser_list_node *a_Node);

		std::map<std::string, widget*> m_PathToWidget;
		std::map<std::string, std::string> m_PathToClass;
		std::map<std::string, properties> m_PathToProperties;

		std::string m_BeginOfPath;
		std::string m_PathSeparator;
		widget_factory m_Factory;
	};

	database_widgets& load_ui(std::istream &a_Stream, bool a_PrettyPrint = false);
	database_widgets& load_ui(const std::string &a_Filename, bool a_PrettyPrint = false);
}
}